package ofdinv

import (
	"encoding/xml"
	"fmt"
	"sort"
)

// TplPageContent 表示模板页面结构（根元素为Page）
type TplPageContent struct {
	XMLName xml.Name   `xml:"http://www.ofdspec.org/2016 Page"` // XML根元素，标识模板页面，包含命名空间
	Area    TplArea    `xml:"Area"`                             // 页面区域定义，包含物理尺寸信息
	Content TplContent `xml:"Content"`                          // 页面内容容器，包含所有图层和对象
}

// TplArea 表示模板页面区域
type TplArea struct {
	XMLName     xml.Name `xml:"Area"`        // XML元素名称，标识页面区域
	PhysicalBox string   `xml:"PhysicalBox"` // 物理区域框坐标，定义页面的实际尺寸和位置
}

// TplContent 表示模板页面内容
type TplContent struct {
	XMLName xml.Name   `xml:"Content"` // XML元素名称，标识页面内容容器
	Layers  []TplLayer `xml:"Layer"`   // 图层集合，每个图层包含不同类型的图形对象
}

// TplLayer 表示模板图层
type TplLayer struct {
	XMLName     xml.Name        `xml:"Layer"`                    // XML元素名称，标识图层
	ID          int             `xml:"ID,attr"`                  // 图层唯一标识符，用于区分不同图层
	DrawParam   string          `xml:"DrawParam,attr,omitempty"` // 绘图参数引用，定义图层的绘制属性（可选）
	TextObjects []TextObject    `xml:"TextObject"`               // 文本对象集合，包含页面中的文本元素
	PathObjects []TplPathObject `xml:"PathObject"`               // 路径对象集合，包含页面中的图形路径
}

// TplPathObject 表示模板路径对象
type TplPathObject struct {
	XMLName         xml.Name        `xml:"PathObject"`            // XML元素名称，标识路径对象
	ID              int             `xml:"ID,attr"`               // 路径对象唯一标识符
	Boundary        Boundary        `xml:"Boundary,attr"`         // 路径对象边界框坐标
	LineWidth       float64         `xml:"LineWidth,attr"`        // 线宽，定义路径描边的宽度
	Join            string          `xml:"Join,attr,omitempty"`   // 路径连接样式，如斜接、圆角等（可选）
	StrokeColor     *TplStrokeColor `xml:"StrokeColor,omitempty"` // 描边颜色定义，包含颜色值和色彩空间（可选）
	AbbreviatedData string          `xml:"AbbreviatedData"`       // 简化的路径数据，描述路径的形状和绘制命令
}

// TplStrokeColor 表示模板描边颜色
type TplStrokeColor struct {
	XMLName    xml.Name `xml:"StrokeColor"`     // XML元素名称，标识描边颜色
	Value      string   `xml:"Value,attr"`      // 颜色值，具体的颜色编码或数值
	ColorSpace string   `xml:"ColorSpace,attr"` // 色彩空间，定义颜色值的解释方式
}

// TplRef 表示模板引用
type TplRef struct {
	XMLName    xml.Name `xml:"Template"`        // XML元素名称，标识模板引用
	TemplateID int      `xml:"TemplateID,attr"` // 模板ID，引用具体模板的标识符
	ZOrder     string   `xml:"ZOrder,attr"`     // 渲染顺序，控制模板在页面中的叠加顺序
}

func (t *TplPageContent) GetAllTextObject() []TextObject {
	var objs []TextObject
	for _, layer := range t.Content.Layers {
		objs = append(objs, layer.TextObjects...)
	}
	return objs
}

func (t *TplPageContent) GetBoundary(item string) Boundary {
	var b Boundary
	tplObjs := t.GetAllTextObject()
	for _, obj := range tplObjs {
		if obj.TextCode.Text == item {
			b = obj.Boundary
		}
	}
	return b
}

// 每次执行本方法，
// 都会先执行一遍(t *TplPageContent) GetAllTextObject() []TextObject，
// 如果代码中需要频繁通过ID获取text，
// 可以直接运行GetAllTextObject() 方法，
// 然后就可以反复使用切片返回值了
func (t *TplPageContent) GetTextByID(ID int) (string, error) {
	for _, obj := range t.GetAllTextObject() {
		if obj.ID == ID {
			return obj.TextCode.Text, nil
		}
	}
	return "", fmt.Errorf("页面中未找到ID为 %d 的映射", ID)
}

// 获取模板页以项目名称为代表的字体size
func (t *TplPageContent) GetItemFontSize() float64 {
	var size float64
	for _, obj := range t.GetAllTextObject() {
		if obj.TextCode.Text == "项目名称" {
			size = obj.Size
		}
	}
	return size
}

// 获取页面的[]TextObject中ID最小的object的文本
func (t *TplPageContent) GetMinimumIDTextObject() (string, error) {
	objs := t.GetAllTextObject()
	if len(objs) == 0 {
		return "", fmt.Errorf("页面中没有TextObject")
	}
	sort.Slice(objs, func(i, j int) bool {
		return objs[i].ID < objs[j].ID
	})
	return objs[0].TextCode.Text, nil
}
